//create 所有的逻辑在这儿

const axios = require('axios');
const ora = require('ora');//loading的样式
const inquirer = require('inquirer');//选择模板
let { promisify } = require('util');
let path = require('path');
let fs = require('fs');
let downloadGit = require('download-git-repo');//拉取模板
//可以把异步的api转换成promise形式
downloadGit = promisify(downloadGit);
let { downLoadDirectory } = require('./constants');

let MetalSmith = require('metalsmith'); //遍历文件夹，找需不需要渲染

//consolidate 统一所有的模板引擎
let {render } = require('consolidate').ejs;
render = promisify(render);
let ncp = require('ncp');
ncp = promisify(ncp);
//create的功能是创建项目
//拉取你自己的所有的项目列出来 让用户选 安装哪个项目 projectName
//选择完成后，在显示所有的版本号 1.0
//可能还需要用户配置一些数据来结合来渲染项目


//https://api.github.com/orgs/zhu-cli/repos 获取组织下的仓库


//获取项目列表
const fetchRepoList = async () => {
  try {
    let { data } = await axios.get('https://api.github.com/orgs/zhu-cli/repos');
    return data;
  } catch (error) {
    console.log('获取项目列表出错', error)
  }
  
}

//抓取tag列表
const fetchTagList = async (repo) => {
  let {data} = await axios.get(`https://api.github.com/repos/zhu-cli/${repo}/tags`);
  return data;
}

//封装loading
const waitFnloading = (fn, message) => async (...args) => {
  let spinner = ora(message);
  spinner.start();
  let result = await fn(...args)
  spinner.succeed();
  return result;
}

let download = async (repo, tag) => {
  let api = `zhu-cli/${repo}`;
  if (tag) {
      api += `#${tag}`;
  }
  let dest = `${downLoadDirectory}/${repo}`;
  await downloadGit(api, dest);
  return dest; //显示下载的最终目录
}


module.exports = async (projectName) => {//projectName是src/mian.js文件第42行的传进参数
  let repos = await waitFnloading(fetchRepoList, 'fetch template ....')();
  repos = repos.map(item => item.name);

  //在获取之前 显示loading 关闭loading
  //选择模板 inquirer
  let { repo } = await inquirer.prompt({//在命令行中询问客户问题
      name: 'repo', //获取选择后的结果
      type: 'list',
      message: 'please choise a template to create project',
      choices: repos,
  });
  // console.log(repo);

  //通过当前选择的项目，拉取对应的版本
  //获取对应的版本号
  let tags = await waitFnloading(fetchTagList, 'fetch tags ....')(repo);
  tags = tags.map((item) => item.name);
  // console.log(tags);
  let { tag } = await inquirer.prompt({
      name: 'tag',
      type: 'list',
      message: 'please choise tags to create project',
      choices: tags
  });
  // console.log(repo,tag);//下载模板 版本
  //把模板放到一个临时目录里存好，以备后期使用
  let result = await waitFnloading(download, 'download template')(repo, tag);
  fs.writeFileSync('./1.js', result)
  //console.log(result);//下载的目录

  //拿到下载的目录 直接拷贝当前执行的目录下即可 ncp


  //有的时候用户可以定制下载模板中的内容，拿package.json文件为例，用户可以根据提示给项目命名、
  //设置描述等，生成最终的package.json文件 ask.json网址：https://github.com/zhu-cli/vue-template/blob/master/ask.js
  //如果有ask.js文件直接下载
  if (!fs.existsSync(path.join(result, 'ask.js'))) {
      //复杂的需要模板熏染 渲染后再拷贝
      //把template下的文件 拷贝到执行命令的目录下
      //在这个目录下 项目名字是否已经存在 如果存在示当前已经存在
      await ncp(result, path.resolve(projectName));
  } else {
      //复杂的模板  把git上的项目下载下来，如果有ask文件就是一个复杂的模板，我们需要用户选择，选择后编译模板  
      // metalsmith--模板编译需要这个包
      //需要渲染模板的接口：https://github.com/zhu-cli/vue-template/blob/master/package.json
      //1.让用户填信息
      await new Promise((resolve, reject) => {
          MetalSmith(__dirname) //如果你传入路径，默认遍历当前路径下的src文件夹
              .source(result)
              .destination(path.resolve(projectName))
              .use(async (files, metal, done) => {
                  // console.log(files)
                  let args= require(path.join(result,'ask.js'));
                  let obj=await inquirer.prompt(args);
                  let meta=metal.metadata();
                  Object.assign(meta,obj);
                  delete files['ask.js'];
                  done();
              })
              .use((files, metal, done) => {
                  let obj=metal.metadata()
                  Reflect.ownKeys(files).forEach(async file=>{
                      //是要处理的文件
                      if(file.includes('js')|| file.includes('json')){
                         let content= files[file].contents.toString();//文件的内容
                          if(content.includes('<%')){
                             conteny=await render(content,obj);
                             files[file].contents=Buffer.from(content);//渲染结果
                          }
                      }
                  })
                  //2.让用户填写的信息取渲染模板
                  //根据用户新的输入 下载模板
                  // console.log(metal.metadata())
                  done();
              })
              .build((err) => {
                  if (err) {
                      reject()
                  }else{
                      resolve();
                  }
              })
      })
  }
}